package com.knowledge.plus.内部类.匿名内部类;

import org.junit.Test;

/**
 * 匿名内部类
 *
 * @author TPF
 * @since 2023/5/25
 */
public class InnerClassDemo {

    /**
     * 1. 不使用匿名内部类来实现抽象方法
     */
    @Test
    public void test1() {
        Person p = new Child();
        p.eat();
    }
    /*
     * 可以看到，我们用Child继承了Person类，然后实现了Child的一个实例，将其向上转型为Person类的引用
     * 但是，如果此处的Child类只使用一次，那么将其编写为独立的一个类岂不是很麻烦？
     * 这个时候就引入了匿名内部类
     */
    /**
     * 2. 匿名内部类的基本实现
     */
    @Test
    public void test2() {
        Person p = new Person() {
            @Override
            public void eat() {
                System.out.println("eat something");
            }
        };
        p.eat();
    }
    /*
     * 可以看到，我们直接将抽象类Person中的方法在大括号中实现了，这样便可以省略一个类的书写
     * 并且，匿名内部类还能用于接口上
     */
    /**
     * 在接口上使用匿名内部类
     */
    @Test
    public void test3() {
        Person2 p = new Person2() {
            @Override
            public void eat() {
                System.out.println("eat something");
            }
        };
        p.eat();
    }
    /*
     * 由上面的例子可以看出，
     * 只要一个类是抽象的或是一个接口，那么其子类中的方法都可以使用匿名内部类来实现
     * 最常用的情况就是在多线程的实现上，因为要实现多线程必须继承Thread类或是继承Runnable接口
     */
    @Test
    public void test4() {
        // Thread类的匿名内部类实现
        Thread t = new Thread() {
            @Override
            public void run() {
                for (int i = 1; i <= 5; i++) {
                    System.out.println(i + " ");
                }
            }
        };
        t.start();

        // Runnable接口的匿名内部类实现
        Runnable r = new Runnable() {
            @Override
            public void run() {
                for (int i = 1; i <= 5; i++) {
                    System.out.println(i + " ");
                }
            }
        };
        Thread t2 = new Thread(r);
        t2.start();

    }

}
